/*
 * Copyright (C) 2006-2012 TongYan Corporation
 * All rights reserved.
 *
 * @brief info:计时器类（测试用）
 *
 * @author: 王哲成 - wangzhecheng@yeah.net
 * @date: 2021.07.12
 * @last modified: 2021-07-12
 *
 */
#ifndef __SG_TIMER_H__
#define __SG_TIMER_H__

#include <chrono>
#include <iostream>
#include <string>
#include <time.h>

#include "SGLog.h"

#define __TIMER_ON__
//#undef __TIMER_ON__

class SGTimer
{
  static size_t nLevel;

public:
  explicit SGTimer(const std::string& name)
    : _name(name + ":")
  {
    ++nLevel;
    log(true, _name + " 开始... ", true, false, false);
  }

  ~SGTimer()
  {
    rlog(_name + " 结束. ");
    --nLevel;
  }

  /**
   * 启动计时
   */
  inline void restart() { _start_time = std::chrono::steady_clock::now(); }

  /**
   * 结束计时
   * @return 返回ms数
   */
  inline float elapsed(bool restart = false)
  {
    _end_time = std::chrono::steady_clock::now();
    std::chrono::duration<float> diff = _end_time - _start_time;
    if (restart)
      this->restart();
    return diff.count() * 1000;
  }

  /**
   * 打印时间并重启计时器
   * @param tip 提示
   */
  void rlog(const std::string& tip = "") { log(true, tip, false, true, false); }

  /**
   * 打印时间
   * @param reset 输出之后是否重启计时器，true重启，false不重启
   * @param unit_ms true是ms，false是s
   * @param tip 输出提示
   * @param kill 输出之后是否退出程序，true退出，false不退出
   */
  void log(bool reset = false, const std::string& tip = "", bool unit_ms = true,
    bool show_time = true, bool kill = false)
  {
    const size_t nTime = static_cast<size_t>(elapsed() / 1000.0);
    const size_t nMinite = nTime / 60;
    const size_t nSecond = nTime % 60;

    std::string margin = "";
    for (size_t i = 0; i != nLevel; ++i)
      margin.append("  ");
    const std::string title = tip.length() > 0 ? tip : _name;
    const std::string strTime =
      unit_ms ? std::to_string(elapsed()) + "ms" : std::to_string(elapsed() / 1000.0) + "s";

    if (show_time)
    {

      if (nTime < 60)
      {
        SG_LOG(margin + title + "消耗时间: " + strTime);
      }
      else
      {
        SG_LOG(margin + title + "消耗时间: " + std::to_string(nMinite) + "m " +
          std::to_string(nSecond) + "s");
      }
    }
    else
      SG_LOG(margin + title);

    if (reset)
      this->restart();

    if (kill)
      exit(5);
  }

private:
  std::chrono::steady_clock::time_point _start_time;
  std::chrono::steady_clock::time_point _end_time;
  std::string _name;
}; // timer

#ifdef __TIMER_ON__

#define CONNECTION(text1, text2) text1##text2
#define CONNECT(text1, text2, text3) CONNECTION(text1, text2)(text3)
#define SG_TIMER(text) SGTimer CONNECT(timer, __LINE__, (text))

#else
#define SG_TIMER(text)
#endif

#endif // !__SG_TIMER_H__
